--
-- Author:      feilong
-- DateTime:    2019-09-4 15:57:48
-- Description: 游戏主逻辑

local skynet = require("skynet")
local Timer = require("Timer")
local FSM = require("FSM")
local reason = require("reason")
local constant = require("constant")

--全局变量本地化
local math_floor = math.floor
local math_random = math.random
local math_abs = math.abs
local table_insert = table.insert
local table_remove = table.remove

local DeskBase = import("DeskBase")
local Desk = class("Desk",DeskBase)

--构造函数
function Desk:ctor()
	self.super:ctor()

end

----------------------------------------------------------------------------------------------
---------游戏
---------------------------------------------------------------------------------------------- 
function Desk:start()
	dbglog("___起动二八杠游戏___")
	self.super.start(self) --基础的对象里在里面有初始化的了
	self.service_closed = nil --服务已关闭
	self.banker = nil --庄家

	--数据初始化
	self:init()

	--状态时间
	self.state_time = {	
		rest = 4,		--休息时间		
		start = 7,		--开始	
		gameover = 12, 	--结算时间
		bet = 15, 		--下注
		stop_bet = 1,   --结束下注
	}
	--游戏状态
	--state1 --eventName --state2 --callback
	self.state_list = {		
		{"bet",			"to_stop_bet", 			"stop_bet", 		function() self:onStopBet() end },				
		{"gameover", 	"to_rest", 				"rest", 			function() self:onRest() end },
		{"rest", 		"to_start", 			"start", 			function() self:onStart() end },			
		{"start", 		"to_start_bet",			"bet", 				function() self:onBet() end },	
		{"stop_bet", 	"to_gameover",			"gameover", 		function() self:onGameOver() end },
	}
	self.fsm = FSM.new(self.state_list) --状态机
	self.timer = Timer.new() --定时器

	self.banker_manager:selectBanker()
	self.banker = self.banker_manager:getBanker()	
	self.old_banker = self.banker
	dbglog("___起动机器人_1__")
	--起动机器人
    self.robot_manager:start()
    self.bairen_desk:specialRobotSitdown()
	dbglog("___游戏桌子起完成_____")

	--启动状态机
	self.fsm:set("rest")
	self:changeState("to_start")

	return true
end

-------------------------------------------------------------------------------
-- private
-------------------------------------------------------------------------------

--初始化
function Desk:init()

	--位置id 1闲 2和 3庄 4闲对 5庄对
	self.pool_name = {
		tian = 1,
		di = 2,
		ren = 3,			
	}
	self.bead = {
		win_id = nil, --1闲 2和 3庄
		pair_id = nil, --1无 2闲对 3庄对
	}
	self.cur_round = 0 --局数 (72局后清数据)
	self.pool_all_bet = {} --各个池已下注总分
	self.pool_user_bet = {} --各池玩家的下注总分
	self.pool_rate = {1,1,1} --各池赔率 1天 2地 3人
	--路单
	self.card_road = {
		{win_lose = {}}, --天 赢1 输0
		{win_lose = {}}, --地 赢1 输0
		{win_lose = {}}, --人 赢1 输0	
	}
	self.cards = {
		{}, --天牌
		{}, --地牌
		{}, --人牌
		{}, --庄牌
	}
	self.card_types = {} --牌型

	self.win_list = {} --天1 地2 人3 庄4(赢1 输0) 
	self.max_pool_id = 3 --下注位置个数
	self.dice_list = {0,0} --骰子
	self.bet_list_name = "ebg_bet_list"
	self.permutation = self:getPermutation({1,2,3,4}) --位置排列

	self.all_bet_chip = 0 --总下注
	self.win_pool_id = {} --当前局赢的池id	
	self.user_bet_list = {} --玩家总下注	

	self.user_win_chip = {} --玩家输赢币，算服务费		
	self.win_pool_list = {} --赢的id历史记录列表 存放 self.bead 对象
	self.system_money_cost = 0 --全局总输赢, 不算服务费
	self.bet_result_list = {} --各个玩家结算结果
	self.banker_win_lose = 0 --庄的输赢

	self.bet_user_list = {} --下注过的玩家列表
	self.real_bet_chip = 0 --真人总下注
	self.real_pool_bet = {} --各池真人下注总额
	self.robot_pool_bet = {} --各池机器人下注总额

	------------牌局记录--------------
	self.win_pool_total_chip = {} --每一个池的总输赢情况
	self.win_pool_chip = {} --每一个池的真玩家总输赢情况
	self.win_pool_user_chip = {} --每一个池的真玩家各输赢情况

	self.loser_list = {} --输的玩家
	self.winner_list = {} --赢的玩家
	self.start_time = 0 --开始时间
	self.end_time = 0 --结束时间
	self.bet_user_num = 0 --下注人数
	self.win_pool_free_list = {} --各池服务费
	------------流水记录--------------
	self.win_chip_list = {} --各玩家所赢的金币，不算服务费
	self.win_free_list = {} --各玩家所交的服务费
	
	self.system_result = 0 --库存控制开的结果
	self.control_uid = nil --控制的个人
	self.system_send_award = false --获得奖励库存
	self.control_result = 0  --系统控制结果 0控制成功 1系统赢钱 2随机

	--开始是给假的记录数据
	self.cur_round = math_random(8, 60)	
	for i=1, self.cur_round do
		local win_id = 0 		
		for pool_id, v in pairs(self.card_road) do 					
			local num = math_random(0, 1)			
			table_insert(self.card_road[pool_id].win_lose, num)
			win_id = win_id + 10^(pool_id - 1) * num
		end
		local bead = {win_id=win_id, pair_id=0}
		table_insert(self.win_pool_list, bead)	
	end

	self:reset()	
end

--重置数据
function Desk:reset()
	--状态时间
	self.state_time = {	
		rest = 4,		--休息时间		
		start = 7,		--开始	
		gameover = 12, 	--结算时间
		bet = 15, 		--下注
		stop_bet = 1,   --结束下注
	}	
	self.cards = {
		{}, --天牌
		{}, --地牌
		{}, --人牌
		{}, --庄牌
	}
	self.card_types = {} --牌型
	self.user_win_chip = {} --玩家输赢币，算服务费	
	self.win_chip_list = {} --各玩家所赢的金币，不算服务费	
	self.win_pool_id = {} --当前局赢的池id
	self.user_bet_list = {} --玩家总下注
	self.win_list = {} --天1 地2 人3 庄4(赢1 输0)
	self.bet_result_list = {} --各个玩家结算结果
	self.all_bet_chip = 0 --总下注

	self.win_free_list = {} --各玩家所交的服务费
	self.win_pool_free_list = {{},{},{}} --各池服务费
	self.system_money_cost = 0 --总输赢
	self.win_pool_total_chip = {} --每一个池的输赢情况
	self.win_pool_chip = {} --每一个池的真玩家输赢情况
	self.win_pool_user_chip = {{},{},{}} --每一个池的真玩家各输赢情况
	self.loser_list = {} --输的玩家
	self.winner_list = {} --赢的玩家	
	self.bet_user_num = 0 --下注人数
	self.real_bet_chip = 0 --真人总下注

	self.system_result = 0 --库存控制开的结果
	self.control_uid = nil --控制的个人	
	self.system_send_award = false --获得奖励库存
	self.control_result = 0  --系统控制结果 0控制成功 1系统赢钱 2随机

	--清下注位置数据
	for i=1,self.max_pool_id do 
		self.pool_all_bet[i] = 0
		self.pool_user_bet[i] = {}
		self.real_pool_bet[i] = 0 --各池真人下注总额
		self.robot_pool_bet[i] = 0 --各池机器人下注总额
	end


	self.rule:shuffle() --洗牌
end


-------------------------------------------------------------------------------
-- callback
-------------------------------------------------------------------------------
--玩家进入消息回调 
function Desk:enterReqCallback(uid, fd, msg)
    local user = self.user_manager:getUser(uid)
	local can_bet_list = self:getCanBetList(self.bet_list_name, user:getCoins())
	user:setCanBetList(can_bet_list)	
    local res = self:getEnterInfo(uid) --桌子状态信息
    -- print("===桌子状态信息======rsp_enter",(res))

    return res
end

--离线回调
function Desk:disconnectCallback(uid)
	local user = self.user_manager:getUser(uid)
	if not user then 
		return 
	end
    --上庄列表处理
    local banker = self.banker_manager:getBanker()
    if self.banker_manager:isInBankerList(uid) then                            
        user:setDisconnect(true)
        --清掉上庄列表的排名
        self.banker_manager:clearBankerList()
        dbglog(uid,'在上庄或上庄列表中离开',user:getName(), user:getFD(), user:getDisconnect())              
    end
    --正在当庄
    if banker:compare(user) then 
        self.banker_manager:setUnbanker(true) 
    end
    return true
end

--离开桌子
function Desk:leaveReqCallback(uid)
	--站起
	--从user_manager中删除
	--发送桌子信息变化到zoneserver
	return true
end



-------------------------------------------------------------------------------
-- 状态
-------------------------------------------------------------------------------

--休息
function Desk:onRest()
	dbglog("____erbagang__onRest")

	--重置数据
	self:reset()
	
	self:removeDisconnect()	--删除离线的玩家
	local user_list = self.user_manager:getUserList()
	for uid, user in pairs(user_list) do 
		if user:isPlayer() and not user:compare(self.banker) then 
			if not user:getBeted() and not self.banker_manager:isBanker(user) and not self.banker_manager:isInBankerList(uid) then 
				--不下注的次数超过5次就踢出桌子
				local no_bet_count = user:getNoBetCount()
				user:setNoBetCount(no_bet_count + 1)			
			    if no_bet_count == 4 then --提示玩家			        
			        self:sendToUser(uid, 'table.NTF_TIPS', {type=0, content = constant.BR_NO_BET_TIP })		        
			    end   
			    if no_bet_count == 6 then 		    	
			        self:kickUser(uid) --踢走			
			    end		      			
			end

			--结算后金币不足坐下条件，需要把他站起
			self:checkStandUpUser(uid)
		end
		user:setInitCoins(user:getCoins()) --游戏开始下注时所拥有的金币值
		user:setPlaying(false)
		user:setBeted(false)
		user:setCurBet(0)
	end
	self.room_config:reload() --配置加载
	self:ntRest()	
	self:checkServiceClose() --每局休息时检查是否已关服		
	self.banker_manager:selectBanker()  
	self.banker = self.banker_manager:getBanker()
    self.robot_manager:loadRobot() --机器人加载


	self.bairen_desk:specialRobotSitdown()

	local callback = function ( ... )			
		self:changeState("to_start")		
	end
	self:setTimer(self.state_time.rest, callback)

end

--开始
function Desk:onStart()
	dbglog("_____erbagang__onStart")		
	self.state_time.start = 7
	if self.banker and self.old_banker then 
		if not self.banker:compare(self.old_banker) then
			self.state_time.start = self.state_time.start + 2
			self.old_banker = self.banker
		end
	end	
	--局数
	self.cur_round = self.cur_round + 1
	if self.cur_round == 73 then --清局记录
		self.card_road = {
			{win_lose = {}}, --天 赢1 输0
			{win_lose = {}}, --地 赢1 输0
			{win_lose = {}}, --人 赢1 输0	
		}
		self.win_pool_list = {} --赢的id历史记录列表 存放 self.bead 对象
		self.cur_round = 1
	end	
	--设置在线玩家开始
	self.user_manager:setAllUserValue("playing", true)
	self.dice_list = {math_random(1,6), math_random(1,6)}
	self.robot_manager:setTotalCoins()
	self:ntStart()
	--开始下注
	self.start_time = os.time()	
	local callback = function ()
		--停止下注		
		self:changeState("to_start_bet")
	end
	self:setTimer(self.state_time.start, callback)

end

--下注
function Desk:onBet()
	dbglog("_____erbagang__onBet")	
	self:ntBet()
	local callback = function ()
		--停止下注		
		self:changeState("to_stop_bet")
	end
	self:setTimer(self.state_time.bet, callback)
end

--停止下注
function Desk:onStopBet()
	self:ntStopBet()
	local callback = function ()
		--停止下注		
		self:changeState("to_gameover")
	end
	self:setTimer(self.state_time.stop_bet, callback)
end



--结算
function Desk:onGameOver()
	dbglog("_____erbagang___onGameOver")
    self.end_time = os.time()
    --取得一个结果的牌
    self:getResult()
    -- local cards = self.rule:getCards() 
    local cards = self.cards
    self.card_types = {
    	self.rule:getCardType(cards[1]),
    	self.rule:getCardType(cards[2]),
    	self.rule:getCardType(cards[3]),
    	self.rule:getCardType(cards[4]),
    }

    --结客户端的数据
    local data = {
    	left_time = self.state_time.gameover,    	
        win_list = {},
        bet_result_list = {},	--各个玩家结算结果 
    }
    self.win_list = {} --天1 地2 人3 庄4(赢1 输0) 
    self.bet_result_list = {} --各个玩家结算结果
    for i=1, 4 do 
    	local temp = {}
    	temp.pool_id = i
    	temp.cards = cards[i]
    	temp.card_type = self.card_types[i]
    	if i < 4 then 
	    	local num = self.rule:compareCard(cards[i], cards[4])
	    	self.win_pool_id[i] = num	    	
	    	temp.win_lose = num
	    	table_insert(self.card_road[i].win_lose, num) 
	    end
	    table_insert(self.win_list, temp)
    end	
	data.win_list = self.win_list

	local win_id = 0 
	for pool_id=1, 3 do			
		local num = self.win_pool_id[pool_id]
		win_id = win_id + 10^(pool_id - 1) * num
	end
	local bead = {win_id=win_id, pair_id=0}
	table_insert(self.win_pool_list, bead)	--给DeskMessage:getTrendInfo 用的


	local total_free = 0 --总的服务费
	--有下注过的
	for uid, _ in pairs(self.user_bet_list) do  
		local user = self.user_manager:getUser(uid)
		self.user_win_chip[uid] = 0 --所赢的币 有下注的返回
		self.win_chip_list[uid] = 0 --输赢的币 无下注的返回
		self.win_free_list[uid] = 0

		local pool_result_list = {}					
		local pool_bet = nil
		for pool_id=1, self.max_pool_id do --每个池是玩家是否有下注
			pool_bet = self.pool_user_bet[pool_id][uid] or 0 --下注额			
			self.win_pool_total_chip[pool_id] = self.win_pool_total_chip[pool_id] or 0 --各池总输赢			
			self.win_pool_chip[pool_id] = self.win_pool_chip[pool_id] or 0
			
			local win_pool_user_chip = self.win_pool_user_chip[pool_id]	--每一个池的真玩家各输赢情况		
			local win_pool_free_list = self.win_pool_free_list[pool_id]
			win_pool_user_chip[uid] = 0
			win_pool_free_list[uid] = 0
			if pool_bet > 0 then --池有下注				
				local win_chip = 0 
				local win_free = 0 --服务费
				self.win_chip_list[uid] = self.win_chip_list[uid] or 0 --无下注的返回
				if self.win_pool_id[pool_id] == 1 then 
					--赢了
					win_chip = math_floor(pool_bet*(1 + self.pool_rate[pool_id]))
					win_free = math_floor(pool_bet * self.room_config:getRoomCost())					
					win_chip = win_chip - win_free
					self.win_chip_list[uid] = self.win_chip_list[uid] + pool_bet*self.pool_rate[pool_id]
					self.win_free_list[uid] = self.win_free_list[uid] + win_free
					win_pool_free_list[uid] = win_free

					self.win_pool_total_chip[pool_id] = self.win_pool_total_chip[pool_id] + pool_bet*self.pool_rate[pool_id]
					if user:isPlayer() then 
						self.win_pool_chip[pool_id] = self.win_pool_chip[pool_id] + pool_bet*self.pool_rate[pool_id]
						win_pool_user_chip[uid] = win_pool_user_chip[uid] + pool_bet*self.pool_rate[pool_id]
					end
				else
					--输了
					self.win_chip_list[uid] = self.win_chip_list[uid] - pool_bet
					self.win_pool_total_chip[pool_id] = self.win_pool_total_chip[pool_id] - pool_bet
					if user:isPlayer() then 
						self.win_pool_chip[pool_id] = self.win_pool_chip[pool_id] - pool_bet
						win_pool_user_chip[uid] = win_pool_user_chip[uid] - pool_bet
					end						
				end
				self.user_win_chip[uid] = self.user_win_chip[uid] + win_chip --有下注的返回
				if win_chip > 0 then 
					local pool_result = {
						side = pool_id,
						result_coins = win_chip,
					}
					table_insert(pool_result_list, pool_result)
				end
			
			end
		end			
		
		--服务费
		local pay_fee = self.win_free_list[uid]
		--总体输赢
		if self.win_chip_list[uid] >= 0 then 
			--增加赢的局数
			user:addWinCount()	
			user:setLatelyWin(true)	--最近20局	
		    --输赢记录列表
		    if user:isPlayer() then 
			    table_insert(self.winner_list, {uid = uid, left_score = user:getCoins(), add_score = self.win_chip_list[uid]-pay_fee, 
	                pay_fee = pay_fee, is_robot = user:isRobot()})
		   	end
		else
			if user:isPlayer() then 
			    table_insert(self.loser_list, {uid = uid, left_score = user:getCoins(), add_score = self.win_chip_list[uid]-pay_fee, 
	                pay_fee = pay_fee, is_robot = user:isRobot()})
			end
		    user:setLatelyWin(false) --最近20局
		end
		--有赢币
		local coins = self.user_win_chip[uid] 
		if coins > 0 then
			--修改数据库	        
	        local ret = self:addChip(uid, coins + pay_fee, reason.WIN_COIN)
	        self:reduceChip(uid, pay_fee, reason.PAY_FEE)	           		   				    
		    --服务费记录
		    self:addFreeChip(uid, self.win_free_list[uid], reason.PAY_FEE)
		    --这里先通知每个人自身金币发生变化		    
			self:ntMoneyChangeToHall(uid, user:getCoins(), constant.MONEY_CHANGED_REASON.erbagang_AUDIT)	
            --对局广播
        	self:sendRealHorseMessage(uid,coins,constant.BROADCAST_IDS.BIDS_EBG) 
		end

		--有下注过
		local user_result = {
			uid = uid,
			position = user:getSeatId(), --=0表示没有位置，=1...6表示对应的位置
			result_coins = self.user_win_chip[uid] - self:getUserBet(uid), --下注前后总的输赢
			side_result = pool_result_list, --每一个区域的输赢情况
			curr_coins = user:getCoins(), --当前的金币，加上输赢后的结果
		}
		table_insert(self.bet_result_list, user_result)
		self:winLoseWater(user, self.user_bet_list[uid], self.win_chip_list[uid], pay_fee)
	    local bet_coins = self.user_bet_list[uid]
	    local produce = self.win_chip_list[uid] + self.user_bet_list[uid]
	    local win_lose = self.win_chip_list[uid] - pay_fee
	    local free = pay_fee
	    self:sendSummary(uid, bet_coins, produce, win_lose, free)		
		--今天玩家流水
		self:addPlayerWater(user, self.win_chip_list[uid])
		--输赢流水
		self:loseWinCoins(user, coins)
		self:checkCaiShen(user, self.win_chip_list[uid] - pay_fee)
		--全局总输赢
		if user:isPlayer() then 
			self.system_money_cost = self.system_money_cost - self.win_chip_list[uid]
			total_free = total_free + pay_fee
		end

	end

	--对庄家进行结算
	if self.banker then 		
		local user = self.banker
		local uid = user:getUid()
		local pool_result_list = {}
		local banker_win_lose = 0 --庄的输赢
		for pool_id, v in pairs(self.win_pool_total_chip) do 
			banker_win_lose = banker_win_lose - v
			local pool_result = {
				side = pool_id,
				result_coins = -v,
			}
			table_insert(pool_result_list, pool_result)			
		end
		self.win_free_list[uid] = 0 --抽水
		local coins = banker_win_lose
		if coins > 0 then 
			self.win_free_list[uid] = banker_win_lose * self.room_config:getRoomCost()
			coins = banker_win_lose - self.win_free_list[uid]
			self:addChip(uid, banker_win_lose, reason.WIN_COIN)
			self:reduceChip(uid, self.win_free_list[uid], reason.PAY_FEE)
			--增加赢的局数
			user:addWinCount()	
			user:setLatelyWin(true)	--最近20局	
			--服务费记录
		    self:addFreeChip(uid, self.win_free_list[uid], reason.PAY_FEE)	
            --对局广播
        	self:sendRealHorseMessage(uid, coins, constant.BROADCAST_IDS.BIDS_EBG)   				
		else
			self:reduceChip(uid, -coins, reason.LOSE_COIN)
			user:setLatelyWin(false) --最近20局
		end
		self.banker_win_lose = coins
	    --这里先通知每个人自身金币发生变化		    
		self:ntMoneyChangeToHall(uid, user:getCoins(), constant.MONEY_CHANGED_REASON.erbagang_AUDIT)
		if user:isPlayer() then --玩家坐庄
			self.system_money_cost = self.system_money_cost - banker_win_lose			
			total_free = total_free + self.win_free_list[uid]	
			table_insert(self.winner_list, {uid = uid, left_score = user:getCoins(), add_score = self.banker_win_lose, 
		                pay_fee = self.win_free_list[uid], is_robot = user:isRobot()})						
		end
		if user:isPlayer() then 
			self.win_chip_list[uid] = banker_win_lose --
			self:winLoseWater(user, 0, banker_win_lose, self.win_free_list[uid])
		    local bet_coins = 0
		    local produce = banker_win_lose
		    local win_lose = coins 
		    local free = self.win_free_list[uid]
		    self:sendSummary(uid, bet_coins, produce, win_lose, free)			

			--今天玩家流水
			self:addPlayerWater(user, banker_win_lose)
			--输赢流水
			self:loseWinCoins(user, banker_win_lose)
			self:checkCaiShen(user, coins)
			--庄输的算流水
			local str_date = os.date("%Y%m%d%H%M%S")    
		    if banker_win_lose < 0 then 
		        billlog({ op   = "water_history",  
		            table_gid  = str_date .. "_" .. self.table_id,
		            table_type = self.table_type,
		            uid        = uid,
		            value      = math_abs(banker_win_lose),
		            is_robot   = false,
		            r          = constant.WATER_TYPE.WATER_BET
		        })
		        --个人流水（用于vip升级
		        R().basesvr({key=uid}):send('.msg_handler','add_person_water', uid, math_abs(banker_win_lose), false)
		    end

		end
		local user_result = {
			uid = uid,
			position = user:getSeatId(), --=0表示没有位置，=1...6表示对应的位置
			result_coins = coins, --下注前后总的输赢
			side_result = pool_result_list, --每一个区域的输赢情况
			curr_coins = user:getCoins(), --当前的金币，加上输赢后的结果
		}
		table_insert(self.bet_result_list, user_result)

		self.bet_user_num = self.bet_user_num + 1 --参与人数
	end

	data.bet_result_list = self.bet_result_list

	-- dbglog("_____erbagang___gameover__",(data))

	--把输赢发送到好友服
	self:sendLoseWinToFriendServer(self.system_money_cost + total_free)
	--库存更新
	self:updateStore()
	--牌局记录
	self:writeCardRecord()	
	--通知客户端
	self:ntGameOver(data)	
	
	local callback = function ()
		--休息		
		self:changeState("to_rest")
	end
	self:setTimer(self.state_time.gameover, callback)
	
	
end

-------------------------------------------------------------------------------
-- 推送消息
-------------------------------------------------------------------------------
function Desk:ntRest()
    self:sendToAllUser('erbagang.NTF_REST',{
        left_time = self.state_time.rest,
    })	
end
function Desk:ntStart()
	local left_time = self.state_time.start
	local banker_info = {
		banker = self.banker:getClientInfo(),
		system_do_banker = self.banker:isRobot() and 1 or 0
	}
	local data = {
        left_time = left_time,
        dice_list = self.dice_list,
        banker_info = banker_info,
    }
    self:sendToAllUser('erbagang.NTF_START', data)
	dbglog("__________ps_ntStart", (data))
end
function Desk:ntBet()	
    self:sendToAllUser('erbagang.NTF_START_BET',{
        left_time = self.state_time.bet,
    })
end
function Desk:ntStopBet()	
    self:sendToAllUser('erbagang.NTF_STOP_BET',{
        left_time = self.state_time.stop_bet,
    })
end
function Desk:ntGameOver(data)	
    -- required uint32 left_time               = 2; //操作时间     
    -- repeated uint32 win_pools               = 3; //赢的池id 1闲 2和 3庄 4闲对 5庄对   
    -- required string win_chip                = 4; //自己赢的筹码数  
    -- repeated PlayerInfo seat_player         = 5; //座位上信息	
    self:sendToAllUser('erbagang.NTF_GAMEOVER', data)
end



---------------------------------------------------------------------------------------------------------



-- private
---------------------------------------------------------------------------------------------------------
--取桌子配置
function Desk:getConfig(user)
  	local room_data = self.room_config:getRoomData()
	return{
		person_limit = room_data.person_limit,
		person_tian_limit = room_data.person_tian_limit,
		person_di_limit = room_data.person_di_limit,
		person_ren_limit = room_data.person_ren_limit,
		area_tian_limit = room_data.area_tian_limit,
		area_di_limit = room_data.area_di_limit,
		area_ren_limit = room_data.area_ren_limit,		   
	    sitdown_chip = room_data.sit_coins_limit, --坐下需要的金币    
	    need_chip_min = room_data.min_bet, --最少携带金这么多币量才可以下注
	    do_banker_coins = room_data.min_banker_coins, --上庄需要的金币
	    chip_list = user:getCanBetList(), --下注筹码列表 {100,1000,5000,10000,50000}
	}
end

--大厅牌中需要的状态
function Desk:getHallStateNum()
    --状态 1修息 2下注 3结算 (每个游戏要自己处理转换)
    --子游戏重写
	-- start
	-- gameover
	-- rest
	-- bet
	-- stop_bet    
    local state = self:getState()
    local state_tb = {
    	start = 1,
    	rest = 1,
    	bet = 2,
    	stop_bet = 3,
    	gameover = 3,
    }
    return state_tb[state]
end

--大厅牌中需要的状态总时间
function Desk:getHallStateTotalTime()   
    local state = self:getState()
    local time_tb = {
    	self.state_time.rest + self.state_time.start,
    	self.state_time.bet,
    	self.state_time.stop_bet + self.state_time.gameover,
    }
    return time_tb
end
function Desk:getHallStateLeftTime()   
	self:getLeftTime()
end

--取下注池信息
function Desk:getPoolList(uid)
	local poolList = {}
	for pool_id=1, self.max_pool_id do 
		local pool = {}
		pool.pool_id = pool_id
		pool.all_bet = self.pool_all_bet[pool_id]
		pool.my_bet = self.pool_user_bet[pool_id][uid]
		pool.rate = self.pool_rate[pool_id] --赔率	
		table_insert(poolList,pool)
	end	
	return poolList
end

--桌子状态信息
function Desk:getEnterInfo(uid)

    local seated_list = {}
    local user = self.user_manager:getUser(uid)
    --有座位的玩家
    local seat_users = self.user_manager:getSeatUsers()
    for _, user in pairs(seat_users) do
    	local info = user:getClientInfo()
        table_insert(seated_list, info)    
    end
	local banker_info = {
		banker = self.banker:getClientInfo(),
		system_do_banker = self.banker:isRobot() and 1 or 0
	}
    local enter_info = {        
        config = self:getConfig(user), --配置
        seated_list = seated_list, --有座位的玩家列表
		bet_pool_list = self:getPoolList(uid), --下注池
		all_bet_chip = self.all_bet_chip, --总注
		card_road = self.card_road, --牌路
		win_list = self.win_list,
		banker_info = banker_info,
		dice_list = self.dice_list,
		left_time = self:getLeftTime(),
		online_num = self.user_manager:getUserNum(),
		state = self:getStateNum(), --桌子状态 
		room_name = self.room_config:getRoomName(), --桌子名
		bet_result_list = self.bet_result_list,  --各个玩家结算结果
    }
    -- dbglog("__222222222222_1__enter_info___", (seated_list))
    return {
        game_type = self.game_type,
        table_type = self.table_type,
        erbagang_enter_info = enter_info,
    }
end

function Desk:getAllBetChip()
	return self.all_bet_chip
end

--玩家下注
function Desk:setUserBet(user, bet_chip, pool_id)
	-- errlog("________setUserBet_____",bet_chip, pool_id)
	local uid = user:getUid()
	--各池玩家的下注总分
	self:addPoolUserBet(pool_id, uid, bet_chip)

	--各个池已下注总分
	self.pool_all_bet[pool_id] = self.pool_all_bet[pool_id] + bet_chip
	--玩家总下注
	if not self.user_bet_list[uid] then 
		self.user_bet_list[uid] = 0 --玩家总下注
	end
	self.user_bet_list[uid] = self.user_bet_list[uid] + bet_chip
	--总注
	self.all_bet_chip = self.all_bet_chip + bet_chip	

	if not user:getBeted() then 
		self.bet_user_num = self.bet_user_num + 1
	end
	if user:isPlayer() then 
		self.real_bet_chip = self.real_bet_chip + bet_chip --真人总下注
		self.real_pool_bet[pool_id] = self.real_pool_bet[pool_id] + bet_chip --各池真人下注总额
	else
		self.robot_pool_bet[pool_id] = self.robot_pool_bet[pool_id] + bet_chip --各池机器人下注总额
	end

end

--各个池已下注总分
function Desk:getPoolAllBet(pool_id)
	return self.pool_all_bet[pool_id] or 0 
end

--各池玩家的下注总分
function Desk:getPoolUserBet(pool_id, uid)
	if not self.pool_user_bet[pool_id] then 
		self.pool_user_bet[pool_id] = {}
	end
	return self.pool_user_bet[pool_id][uid] or 0 
end

function Desk:addPoolUserBet(pool_id, uid, bet_chip)
	if not self.pool_user_bet[pool_id] then 
		self.pool_user_bet[pool_id] = {}
	end
	if not self.pool_user_bet[pool_id][uid] then 
		self.pool_user_bet[pool_id][uid] = 0
	end
	self.pool_user_bet[pool_id][uid] = self.pool_user_bet[pool_id][uid] + bet_chip
end

--玩家的下注总分
function Desk:getUserBet(uid)
	return self.user_bet_list[uid] or 0 
end

--排列
function Desk:getPermutation(list)
    local res = {}
    local function permute(a,k)
        local len = #a
        if(len == k) then
            local b = {}
            for i,j in pairs(a) do
                 b[i] = j
             end
            table_insert(res,b)
        else
            for i=k, len do
                a[i], a[k] = a[k], a[i]
                permute(a,k+1)
                a[i], a[k] = a[k], a[i]
            end
        end
    end
    permute(list,1)
    return res
end






---------------------------------------------------------------------------------------------------------



-- 
---------------------------------------------------------------------------------------------------------

--牌局记录
function Desk:writeCardRecord()
    local side_list = {} --池信息
    local banker_id = self.banker:getUid()
    for pool_id=1, self.max_pool_id do 
	    local player_bet_list = {} --玩家下注列表
	    local player_win_list = {} --玩家输赢列表    	
	    local user = nil
	    local win_pool_user_chip = self.win_pool_user_chip[pool_id]    
	    for uid, win_coins in pairs(win_pool_user_chip) do
	        user = self.user_manager:getUser(uid)
	        if user:isPlayer() then 
	            table_insert(player_win_list,{uid = uid, win_coins = win_coins})
	        end
	    end    	       	
        local side_bet_list = self.pool_user_bet[pool_id]
        for uid, coins in pairs(side_bet_list) do
            user = self.user_manager:getUser(uid)
            if user:isPlayer() then 
            	table_insert(player_bet_list,{uid = uid, bet_coins = coins})
            end            
        end

    	--玩家输赢详情
    	local side_info = {
			side = 0, --下注的池位置
			cards = {}, --牌
			card_type = 0, --牌型			
			bet_coins = 0, --池下注总额
			player_bet_coins = 0, --玩家总下注额
			total_side_win = 0, --池总输赢
			player_side_win = 0, --玩家输赢
			player_win_list = {}, --玩家输赢列表
			player_bet_list = {}, --玩家下注列表
			banker_id = banker_id, --庄家id
    	} 
		side_info.side = pool_id
		side_info.cards = self.cards[pool_id]
		side_info.card_type = self.card_types[pool_id]
		side_info.bet_coins = self.pool_all_bet[pool_id]
		side_info.player_bet_coins = self.real_pool_bet[pool_id]
		side_info.total_side_win = self.win_pool_total_chip[pool_id]
		side_info.player_side_win = self.win_pool_user_chip[pool_id][uid]
		side_info.player_win_list = player_win_list
		side_info.player_bet_list = player_bet_list

		table_insert(side_list, side_info)
   	end 
   	--庄家特殊处理
	local side_info = {
		side = 4, --下注的池位置
		cards = self.cards[4], --牌
		card_type = self.card_types[4], --牌型		
		bet_coins = 0, --池下注总额
		player_bet_coins = 0, --玩家总下注额
		total_side_win = self.banker_win_lose, --池总输赢
		player_side_win = 0, --玩家输赢
		player_win_list = {}, --玩家输赢列表
		player_bet_list = {}, --玩家下注列表
		banker_id = banker_id, --庄家id
	}    	
	if self.banker:isPlayer() then 
		table_insert(side_info.player_win_list,{uid = banker_id, win_coins = self.banker_win_lose})	
	end
	table_insert(side_list, side_info)


   	local table_gid = os.date("%Y%m%d%H%M%S") .."_".. self.table_id
   	--system_result  	
   	local record = {
		exinfo = {
			system_result = self.system_result, --系统控制类型
			control_uid = self.control_uid or 0, 
			err_result = self.control_result,
		},
		end_time = self.end_time,
		begin_time = self.start_time,
		total_num = self.bet_user_num, --参加游戏人数
		loser_list = self.loser_list,
		winner_list = self.winner_list,
		curr_round = self.cur_round,
		table_gid = table_gid,
		game_type = self.game_type,
		address = skynet.address(skynet.self()),
		table_type = self.table_type,
		side_list= side_list, --详情
		op= "card_record",		  
	}
    billlog(record)

    dbglog("__card_record__牌局记录___________",(record))
end


--库存控制
--1. 系统控制后提出需求 吃或放
--2. 给出一个游戏结果
--3. 计算输赢是否满足需求
--跟据库存开出游戏结果
function Desk:getResult()
	--store_result 1系统赢 2、系统输 0、随机
    local store_result, personal_uid = self.store_manager:getSystemStoreResult(self.banker)
    self.system_result = store_result --系统控制类型
    self.control_uid = personal_uid --gm控制玩家uid
    if not store_result then
        errlog("failed to get store_result",store_result,personal_uid)
        return
    end
    dbglog("system___control__result__",store_result,personal_uid)
	if self.system_result == constant.AWARD_STORE_LOSE then --系统输
		self.system_send_award = true --获得奖励库存
	end

    --随机一组牌, 不同的顺序组成一个
    --检查结果是否符合库存要求，
    local base_cards = self.rule:getCards() --取出牌
    if self.rule:isPeiPai() then 
    	self.cards = base_cards
    	return true
    end
    --给出一个游戏结果
    local cards_res = {}
    for i=1, #self.permutation do 
	    local permut = self.permutation[i]
	    local cards = {
	    	base_cards[permut[1]],
	    	base_cards[permut[2]],
	    	base_cards[permut[3]],
	    	base_cards[permut[4]],
	    }
	    local check_pass = self:checkResult(cards)
	    if check_pass then 	    
		    table_insert(cards_res, cards)	
	    end		
	end
	if next(cards_res) then 
		local index = math_random(1, #cards_res)
		self.cards = cards_res[index]
		self.control_result = 0
		return 
	end
	if self.control_result == 1 then --控制结果不满足需求
		--杀	    
	    self.system_result = constant.SYSTEM_STORE_WIN --库存1赢钱 
	    if self.control_uid then 
	    	self.system_result = constant.PERSONAL_STORE_LOSE
	    end
	    local check_pass = false
		for i=1, #self.permutation do 
		    local permut = self.permutation[i]
		    local cards = {
		    	base_cards[permut[1]],
		    	base_cards[permut[2]],
		    	base_cards[permut[3]],
		    	base_cards[permut[4]],
		    }
		    check_pass = self:checkResult(cards)
		    if check_pass then 	    
			    self.cards = cards
			    break
		    end		
		end	
		if check_pass then 
			return 
		end
		self.control_result = 2 --杀不住
		self.system_result = constant.SYSTEM_NO_CONTROL --随机 
	end

	dbglog("------erbagang无法满足条件随机出结果----------")
	--随机
	self.cards = base_cards
end

--检查结果是否符合库存
function Desk:checkResult(cards)
    --存在一个系统是庄或玩家是庄的问题
	--玩家是庄
	--1要个人控制的是庄
	--2要个人控制的不是庄

    local robot_store = self.room_config:getRobotStore()    
    local lose_limit = robot_store.base_lose_limit or 100000 --库存单局输钱上限
    if self.system_result == constant.AWARD_STORE_LOSE then --奖励库单局输钱上限
        lose_limit = robot_store.award_lose_limit or 100000
    end
    local bet_coins = self.real_bet_chip --总下注额
    local real_pool_bet = self.real_pool_bet --各池真人下注总额
    local robot_pool_bet = self.robot_pool_bet --各池机器人下注总额
    local pool_bet = {} --各池的下注值
    local win_pools = {} --各池结果
    local win_chip = 0 --玩家总的赢钱
	--大小结果
	local tian_cards = cards[1]
	local di_cards = cards[2]
	local ren_cards = cards[3]
	local banker_cards = cards[4]
    local win_pools = {} --天1 地2 人3 庄4(赢1 输0)     
    win_pools[1] = self.rule:compareCard(tian_cards, banker_cards)
    win_pools[2] = self.rule:compareCard(di_cards, banker_cards)
    win_pools[3] = self.rule:compareCard(ren_cards, banker_cards)

    if self.banker:isRobot() then 
    	pool_bet = real_pool_bet
	    if self.control_uid then --对个人控制
	    	bet_coins = self:getUserBet(self.control_uid)
	    	pool_bet = {}
	    	for pool_id=1, self.max_pool_id do
	    		pool_bet[pool_id] = self:getPoolUserBet(pool_id, self.control_uid)
	    	end
	    end	    

	else
		--真人做庄
    	pool_bet = robot_pool_bet
	    -- if self.control_uid and self.banker:getUid() ~= self.control_uid then --对个人控制
	    -- 	bet_coins = self:getUserBet(self.control_uid)
	    -- 	pool_bet = {}
	    -- 	for pool_id=1, self.max_pool_id do
	    -- 		pool_bet[pool_id] = self:getPoolUserBet(pool_id, self.control_uid)
	    -- 	end
	    -- end
	    -- if self.control_uid and self.banker:getUid() == self.control_uid then --对个人控制庄
	    -- 	bet_coins = self.all_bet_chip
	    -- 	pool_bet = {}
	    -- 	for pool_id=1, self.max_pool_id do
	    -- 		-- pool_bet[pool_id] = real_pool_bet[pool_id] + robot_pool_bet[pool_id]
	    -- 		pool_bet[pool_id] = robot_pool_bet[pool_id]
	    -- 	end
	    -- end	    	
	    bet_coins = 0 --机器人总下注额
    	for pool_id=1, self.max_pool_id do
    		bet_coins = bet_coins + robot_pool_bet[pool_id]
    	end	    			    
	end

    for pool_id=1, 3 do 
    	if win_pools[pool_id] == 1 then 
	        local award_coins = pool_bet[pool_id] * (1 + self.pool_rate[pool_id])
	        win_chip = win_chip + award_coins
	    end
    end
    win_chip = win_chip - bet_coins 

	if self.banker:isPlayer() then --玩家坐庄
		win_chip = - win_chip
	end
	dbglog("________banker_id__", self.banker:getUid(), self.banker:isPlayer())
    dbglog("______self.system_result_______", self.system_result, win_chip)
    dbglog("___________result___",win_pools, bet_coins, lose_limit)
    if win_chip > lose_limit then --是否超过系统输钱上限， 这个游戏结果不通过
    	self.control_result = 1
    	errlog("___erbagang___over__lose_limit___", self.system_result, win_chip, lose_limit)
    	return false
    end
    if self.system_result == constant.SYSTEM_NO_CONTROL then --随机时才放到结果里
    	return true
    end

    if win_chip < 0 then 
    	--系统赢
    	if self.system_result == constant.PERSONAL_STORE_LOSE then 
    		return true
    	end     	
   
    	if self.system_result == constant.SYSTEM_STORE_WIN then --系统赢    		
    		return true
    	end
    elseif win_chip > 0 then 
    	--系统输
    	if self.system_result == constant.PERSONAL_STORE_WIN then   		
    		return true
    	end     	
    	if self.system_result == constant.AWARD_STORE_LOSE then 
    		return true
    	end
    	if self.system_result == constant.SYSTEM_STORE_LOSE then     		
    		return true
    	end       	
    end

    return false

end

--库存处理
function Desk:updateStore()
	local gm_store_coins = 0 --个人控制结果金币的输赢
	--更新个人库存
	if self.control_uid and self.win_chip_list[self.control_uid]  then 
		self.control_coins = self.win_chip_list[self.control_uid]
		gm_store_coins = self.store_manager:updatePersionStore(self.system_money_cost, self.control_coins, self.control_uid, self.system_result )
	end
	--更新系统库存
	self.store_manager:updateSystemStore(self.system_money_cost - gm_store_coins, self.system_send_award)
	dbglog("________updateSystemStore_________", self.system_money_cost, gm_store_coins ,self.system_send_award)
	if not self.system_send_award or self.control_result ~= 0 then
		--更新抽水库存,奖励库
		self.store_manager:updateRobotStore(math_abs(self.system_money_cost) - math_abs(gm_store_coins))
	end
	self.store_manager:checkStoreTransfer()
end



return Desk